#!/usr/bin/env python
'''MainWindow

class that handles the main window
'''

import pygtk
pygtk.require("2.0")
import gtk
import gobject

import About
import AddNumber
import Config
import Gui
import PhoneBook

class MainWindow(gtk.Window):
    '''Display the main window of the program'''

    def __init__(self, type=gtk.WINDOW_TOPLEVEL):
        '''Initialize the window'''
        gtk.Window.__init__(self, type)

        # take the phonebook
        self.book = PhoneBook.PhoneBook()

        self.set_size_request(420, 400)
        self.set_title(Config.get_config("title"))

        self.connect("destroy", self.windowDestroy)
        ui = self.windowSetupMenu()

        main_vbox = gtk.VBox(False, 0)
        self.add(main_vbox)

        main_vbox.pack_start(ui.get_widget("/MainMenu"), False, False, 5)
        self.windowSetup(main_vbox)

        self.show_all()

    def windowDestroy(self, window):
        '''Exiting method'''
        self.hide()
        gtk.main_quit()


    def windowSetup(self, main_vbox):
        '''Calls the main methods that set up the interface'''
        self.windowSetupFilter(main_vbox)
        self.windowSetupNumberList(main_vbox)


    def windowSetupFilter(self, main_vbox):
        '''Set up the filter interface'''
        hbox = gtk.HBox(False, 5)

        label = gtk.Label(_("Filter: "))
        entry = gtk.Entry()

        entry.connect("changed", self.windowUpdateFilter)
        self.filter_text = entry

        hbox.pack_start(label, False, False, 5)
        hbox.pack_start(entry, True, True, 5)

        main_vbox.pack_start(hbox, False, False, 0)


    def windowUpdateFilter(self, widget):
        '''Callback procedure that gets called when the filter box is edited'''
        text = self.filter_text.get_text()
        self.list_model.clear()

        if text == "":
            self.windowUpdateListView(self.book.get_all())
            self.filter_text.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("white"))
        else:
            try:
                self.windowUpdateListView(self.book.get_filtered(text))
                self.filter_text.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("white"))
            except:
                self.windowUpdateListView(self.book.get_all())
                # if the regexp is invalid, make the filter entry red
                self.filter_text.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFAFAF"))

    def windowUpdate(self):
        '''Update the list_model according to the filter text (just a wrapper func)'''
        self.windowUpdateFilter(self.filter_text)


    def windowSetupNumberList(self, main_vbox):
        '''Builds the ListView interface'''
        list_model = gtk.ListStore( gobject.TYPE_STRING,    # name
                                    gobject.TYPE_STRING,    # phone number
                                    gobject.TYPE_STRING)    # comment
        list_view = gtk.TreeView()
        list_view.set_model(list_model)

        cell_name = gtk.CellRendererText()
        cell_name.set_property("editable", True)
        cell_name.connect("edited", self.editName)
        cell_number = gtk.CellRendererText()
        cell_number.set_property("editable", True)
        cell_number.connect("edited", self.editNumber)
        cell_comment = gtk.CellRendererText()
        cell_comment.set_property("editable", True)
        cell_comment.connect("edited", self.editComment)

        col_name = gtk.TreeViewColumn(_("Name"), cell_name, text = 0)
        col_number = gtk.TreeViewColumn(_("Phone Number"), cell_number, text = 1)
        col_comment = gtk.TreeViewColumn(_("Comment"), cell_comment, text = 2)

        col_name.set_resizable(True)
        col_number.set_resizable(True)
        col_comment.set_resizable(True)

        list_view.append_column(col_name)
        list_view.append_column(col_number)
        list_view.append_column(col_comment)

        n_read = self.book.get_all()

        self.list_model = list_model
        self.list_view = list_view
        self.windowUpdateListView(n_read)

        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
        sw.add(list_view)
        sw.show_all()

        main_vbox.pack_start(sw, True, True, 5)


    def editName(self, widget, path, new_name):
        '''Callback function called when we edit the name column'''
        self.book.update_name(path, new_name)
        self.windowUpdate()


    def editNumber(self, widget, path, new_number):
        '''Callback function called when we edit the number column'''
        self.book.update_number(path, new_number)
        self.windowUpdate()

    def editComment(self, widget, path, new_comment):
        '''Callback function called when we edit the comment column'''
        self.book.update_comment(path, new_comment)
        self.windowUpdate()


    def windowUpdateListView(self, list):
        '''Add items to the list view'''
        try:
            for csv_name, csv_number, csv_comment in list:
                iter = self.list_model.append(None)
                self.list_model.set_value(iter, 0, csv_name)
                self.list_model.set_value(iter, 1, csv_number)
                self.list_model.set_value(iter, 2, csv_comment)
        except:
            Gui.ErrorBox(self, _("Error in book.csv file!"))


    def windowSetupMenu(self):
        '''Build the menu'''
        ui_info = \
                '''
                <ui>
                    <menubar name="MainMenu">
                        <menu action="Phonebook">
                            <menuitem action="Phonebook_add" />
                            <menuitem action="Phonebook_del" />
                            <separator />
                            <menuitem action="Quit" />
                        </menu>
                        <menu action="Help">
                            <menuitem action="HelpAbout" />
                        </menu>
                    </menubar>
                </ui>
                '''

        entries = (
                ( "Phonebook", None, _("_PhoneBook") ),
                ( "Phonebook_add", gtk.STOCK_ADD,
                    _("Add..."), "<control>A",
                    _("Add a new telephone number"),
                    self.windowAddNumber),
                ( "Phonebook_del", gtk.STOCK_DELETE,
                    _("Delete selected..."), "<control>D",
                    _("Delete the selected phone number"),
                    self.windowDelNumber),
                ( "Quit", gtk.STOCK_QUIT,
                    _("Quit"), "<control>W",
                    _("Quit"),
                    self.windowQuit),
                ( "Help", None, _("_Help") ),
                ( "HelpAbout", gtk.STOCK_ABOUT,
                    _("About..."), None,
                    _("About the program"),
                    self.windowAbout),
        )

        actions = gtk.ActionGroup("actions")
        actions.add_actions(entries)

        ui = gtk.UIManager()
        ui.insert_action_group(actions, 0)
        self.add_accel_group(ui.get_accel_group())

        try:
            mergeid = ui.add_ui_from_string(ui_info)
        except:
            Gui.ErrorBox(self, _("Can't build menu!"))
            sys.exit(False)

        return ui


    def windowAddNumber(self, action):
        '''Call the add number's dialog'''
        AddNumber.AddNumber(self)


    def windowDelNumber(self, action):
        '''Call the delete number's dialog'''
        model, iterator = self.list_view.get_selection().get_selected()
        if not iterator:
            Gui.ErrorBox(self, _("Select an item to delete first!"))
        else:
            yesno = gtk.MessageDialog(self, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
                    _("Do you really want to delete this number from the phonebook?"))

            def delNumberResponse(window, response_id):
                if response_id == gtk.RESPONSE_YES:
                    path = self.list_model.get_path(iterator)[0]
                    self.list_model.remove(iterator)
                    self.book.remove_number(path)
                yesno.destroy()

            yesno.connect("response", delNumberResponse)
            yesno.show()


    def windowAbout(self, action):
        '''Display the about window'''
        About.AboutWindow()


    def windowQuit(self, action):
        '''Method used for leaving the program'''
        return self.windowDestroy(self)

